package com.srmt.document.feishu.internal;

import com.lark.oapi.service.docx.v1.model.*;
import com.srmt.common.config.ApplicationConfig;
import com.srmt.document.api.ContentWriter;
import com.srmt.document.exception.CellException;
import com.srmt.document.exception.ContentException;
import com.srmt.document.exception.DocumentOperationException;
import com.srmt.document.exception.TableException;
import com.srmt.document.feishu.internal.core.BlockContext;
import com.srmt.document.feishu.internal.table.TableOperationStrategy;
import com.srmt.document.feishu.internal.table.TableStrategyFactory;
import com.srmt.document.feishu.internal.writer.*;
import com.srmt.document.model.ColumnData;
import com.srmt.document.model.RowData;
import com.srmt.document.table.model.TableType;
import com.srmt.feishu.client.FeishuClient;
import com.srmt.feishu.client.model.ProtectedDimension;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * 飞书内容写入器实现（重构版）
 *
 * <p>作为协调者（Coordinator），将所有写操作委托给专门的服务类处理。
 *
 * <h3>设计原则：</h3>
 * <ul>
 *   <li><b>协调者模式</b>：仅负责方法路由，不包含业务逻辑</li>
 *   <li><b>单一职责</b>：每个操作委托给专门的服务类处理</li>
 *   <li><b>策略模式</b>：不同表格类型使用不同的操作策略</li>
 * </ul>
 *
 * <h3>服务类委托：</h3>
 * <ul>
 *   <li>{@link TextOperationService} - 文本操作（插入、替换）</li>
 *   <li>{@link TableRowOperationService} - 行操作（添加、删除）</li>
 *   <li>{@link TableColumnOperationService} - 列操作（添加、删除）</li>
 *   <li>{@link CellOperationService} - 单元格操作（读写、合并）</li>
 *   <li>{@link SheetProtectionService} - Sheet保护操作</li>
 * </ul>
 *
 * <h3>重构历史：</h3>
 * <ul>
 *   <li>v2.0.0: 初始拆分 - 从1396行拆分到1274行（-8.7%）</li>
 *   <li>v3.0.0: 深度优化 - 从1291行优化到489行（-62.1%）</li>
 * </ul>
 *
 * @author srmt
 * @since 2.0.0
 * @version 3.0.0 深度优化，完全委托化
 */
public class FeishuContentWriter implements ContentWriter {
    
    private static final Logger logger = LoggerFactory.getLogger(FeishuContentWriter.class);
    
    private final FeishuClient client;
    private final FeishuIndexResolver indexResolver;
    private final TableStrategyFactory strategyFactory;
    private final TextOperationService textOperationService;
    private final CellOperationService cellOperationService;
    private final TableRowOperationService tableRowOperationService;
    private final TableColumnOperationService tableColumnOperationService;
    private final SheetProtectionService sheetProtectionService;
    
    // 批量更新的最大请求数
    private static final int MAX_BATCH_SIZE = 100;
    
    /**
     * 使用ApplicationConfig构造（推荐）
     */
    public FeishuContentWriter(FeishuClient client, ApplicationConfig applicationConfig) {
        if (client == null) {
            throw new IllegalArgumentException("客户端不能为null");
        }
        if (applicationConfig == null) {
            throw new IllegalArgumentException("应用配置对象不能为null");
        }
        this.client = client;
        this.indexResolver = new FeishuIndexResolver(client);
        this.strategyFactory = TableStrategyFactory.create(client);
        this.textOperationService = new TextOperationService(client);
        this.cellOperationService = new CellOperationService(client);
        this.tableRowOperationService = new TableRowOperationService(client);
        this.tableColumnOperationService = new TableColumnOperationService(client);
        this.sheetProtectionService = new SheetProtectionService(client);
    }
    
    
    /**
     * 将公共API的TableType转换为内部使用的TableType
     * 
     * @param publicTableType 公共API的TableType
     * @return 内部TableType
     */
    private com.srmt.document.feishu.internal.table.model.TableType convertToInternalTableType(TableType publicTableType) {
        if (publicTableType == null) {
            return com.srmt.document.feishu.internal.table.model.TableType.UNKNOWN;
        }
        
        switch (publicTableType) {
            case NORMAL_TABLE:
                return com.srmt.document.feishu.internal.table.model.TableType.NORMAL_TABLE;
            case SHEET:
                return com.srmt.document.feishu.internal.table.model.TableType.SHEET;
            case BITABLE:
                return com.srmt.document.feishu.internal.table.model.TableType.BITABLE;
            case UNKNOWN:
            default:
                return com.srmt.document.feishu.internal.table.model.TableType.UNKNOWN;
        }
    }
    
    // ============ 文本操作 ============
    
    @Override
    public void appendTextAfter(String docId, String anchorText, String text) throws ContentException {
        textOperationService.appendTextAfter(docId, anchorText, text);
    }

    @Override
    public void insertTextBefore(String docId, String anchorText, String text) throws ContentException {
        textOperationService.insertTextBefore(docId, anchorText, text);
    }
    
    @Override
    public void replaceText(String docId, String oldText, String newText) throws ContentException {
        textOperationService.replaceText(docId, oldText, newText);
    }

    @Override
    public int replaceAllText(String docId, String oldText, String newText) throws ContentException {
        return textOperationService.replaceAllText(docId, oldText, newText);
    }

    @Override
    public int replaceTextByPattern(String docId, String pattern, String replacement) throws ContentException {
        return textOperationService.replaceTextByPattern(docId, pattern, replacement);
    }
    
    // ============ 表格创建 ============
    
    @Override
    public void createTable(String docId, String anchorText, int rows, int cols, 
                          List<List<String>> content) throws TableException {
        // 默认创建普通表格
        createTable(docId, anchorText, rows, cols, content, TableType.NORMAL_TABLE);
    }
    
    @Override
    public void createTable(String docId, String anchorText, int rows, int cols, 
                          List<List<String>> content, TableType tableType) throws TableException {
        logger.debug("在文档 {} 中创建 {}x{} {}", rows, cols, tableType.getDescription(), docId);
        
        try {
            // 验证参数
            if (rows <= 0 || cols <= 0) {
                throw new IllegalArgumentException("无效的表格维度: " + rows + "x" + cols);
            }
            
            // 验证内容与表格大小匹配
            if (content != null && !content.isEmpty()) {
                if (content.size() != rows) {
                    throw new IllegalArgumentException(String.format(
                        "Content row count %d doesn't match table rows %d", 
                        content.size(), rows));
                }
                for (int i = 0; i < content.size(); i++) {
                    List<String> row = content.get(i);
                    if (row != null && row.size() != cols) {
                        throw new IllegalArgumentException(String.format(
                            "Row %d has %d columns, but table expects %d columns",
                            i, row.size(), cols));
                    }
                }
            }
            
            // 直接使用策略创建指定类型的表格结构
            com.srmt.document.feishu.internal.table.model.TableType internalTableType = convertToInternalTableType(tableType);
            TableOperationStrategy strategy = strategyFactory.getStrategy(internalTableType);
            Block[] tableBlocks = strategy.createTableStructure(rows, cols, content);
            
            // 创建上下文
            BlockContext context = new BlockContext(client, docId);
            
            // 确定插入位置
            String parentBlockId;
            int insertIndex;
            
            Block pageBlock = context.getPageBlock();
            if (pageBlock == null) {
                throw new TableException("未找到页面块");
            }
            parentBlockId = pageBlock.getBlockId();
            
            if (anchorText != null && !anchorText.isEmpty()) {
                // 查找锚点Block
                Block anchorBlock = context.findBlockByAnchor(anchorText);
                if (anchorBlock != null) {
                    // 使用IndexResolver计算正确的插入索引
                    insertIndex = indexResolver.getSafeInsertIndex(
                        docId, parentBlockId, anchorBlock.getBlockId(), true);
                    
                    logger.debug("解析出锚点 '{}' 后的表格插入索引 {}", 
                               insertIndex, anchorText);
                } else {
                    logger.warn("未找到锚点,将表格追加到末尾");
                    insertIndex = -1;
                }
            } else {
                // 在文档末尾插入
                insertIndex = -1; // -1表示追加到末尾
            }
            
            // 提取子Block ID（第一个是Table Block）
            String[] childrenIds = new String[]{tableBlocks[0].getBlockId()};
            
            // 创建表格
            CreateDocumentBlockDescendantReq createReq = CreateDocumentBlockDescendantReq.newBuilder()
                    .documentId(docId)
                    .blockId(parentBlockId)
                    .documentRevisionId(-1)
                    .createDocumentBlockDescendantReqBody(CreateDocumentBlockDescendantReqBody.newBuilder()
                            .childrenId(childrenIds)
                            .index(insertIndex)
                            .descendants(tableBlocks)
                            .build())
                    .build();
            
            // createDocumentBlockDescendant现在直接返回数据体，失败时抛出FeishuApiException
            client.docx().createDocumentBlockDescendant(createReq);
            
            logger.info("成功创建包含 {} 行 {} 列的表格", rows, cols);
            
            // 对于电子表格类型，需要重新获取文档以获取自动生成的token
            if (tableType == TableType.SHEET) {
                try {
                    // 给飞书更多时间完成电子表格的创建和初始化
                    Thread.sleep(2000);
                    
                    // 重新获取文档blocks（此时应该包含完整的Sheet信息）
                    BlockContext newContext = new BlockContext(client, docId);
                    
                    // 查找刚创建的电子表格block
                    // 策略：找到锚点后的第一个Sheet块，或者最后一个Sheet块（如果没有锚点）
                    Block createdSheetBlock = null;
                    
                    if (anchorText != null && !anchorText.isEmpty()) {
                        // 有锚点：查找锚点后的第一个Sheet
                        Block sheetAfterAnchor = newContext.findTableAfterAnchor(anchorText);
                        if (sheetAfterAnchor != null && sheetAfterAnchor.getSheet() != null) {
                            createdSheetBlock = sheetAfterAnchor;
                        }
                    } else {
                        // 无锚点：找最后一个Sheet（刚创建的）
                        List<Block> allBlocks = newContext.getBlocks();
                        for (int i = allBlocks.size() - 1; i >= 0; i--) {
                            Block block = allBlocks.get(i);
                            if (block.getBlockType() == 30 && block.getSheet() != null) {
                                createdSheetBlock = block;
                                break;
                            }
                        }
                    }
                    
                    if (createdSheetBlock != null && createdSheetBlock.getSheet() != null 
                        && createdSheetBlock.getSheet().getToken() != null) {
                        Sheet retrievedSheet = createdSheetBlock.getSheet();
                        String sheetToken = retrievedSheet.getToken();
                        logger.info("获取自动生成的工作表令牌: {}", sheetToken);
                        
                        // 如果有初始内容，现在可以通过Sheets API设置
                        if (content != null && !content.isEmpty()) {
                            try {
                                // 正确解析token（使用lastIndexOf，因为spreadsheetToken本身可能包含下划线）
                                String spreadsheetToken;
                                String sheetId;
                                int lastUnderscoreIndex = sheetToken.lastIndexOf('_');
                                
                                if (lastUnderscoreIndex == -1) {
                                    // 没有下划线，整个token就是spreadsheetToken
                                    spreadsheetToken = sheetToken;
                                    sheetId = ""; // 默认第一个sheet
                                } else {
                                    // 有下划线，分割token
                                    spreadsheetToken = sheetToken.substring(0, lastUnderscoreIndex);
                                    sheetId = sheetToken.substring(lastUnderscoreIndex + 1);
                                }
                                
                                // 构建range（第一个sheet的范围）
                                // 注意: buildRange需要1-based索引,所以从0开始的索引需要+1
                                String range = com.srmt.document.feishu.internal.table.util.SheetCoordinateHelper
                                        .buildRange(sheetId, 1, 1, rows, cols);
                                
                                // 使用SheetsService设置初始内容
                                boolean success = client.sheets().updateValues(spreadsheetToken, range, content);
                                if (success) {
                                    logger.info("成功设置嵌入式工作表的初始内容");
                                } else {
                                    logger.warn("设置嵌入式工作表的初始内容失败");
                                }
                            } catch (Exception e) {
                                logger.warn("设置工作表初始内容失败: {}", e.getMessage());
                            }
                        }
                    } else {
                        logger.warn("创建工作表后无法获取自动生成的工作表令牌");
                    }
                } catch (Exception e) {
                    logger.warn("创建后获取工作表令牌失败: {}", e.getMessage());
                }
            }
            
        } catch (DocumentOperationException e) {
            throw new TableException("创建表格失败: " + e.getMessage());
        } catch (Exception e) {
            if (e instanceof IllegalArgumentException) {
                throw (IllegalArgumentException) e;  // 不要包装IllegalArgumentException
            }
            if (e instanceof TableException) {
                throw (TableException) e;
            }
            throw new TableException("创建表格失败: " + e.getMessage());
        }
    }
    
    // ============ 表格操作 - 按行 ============
    
    @Override
    public void addTableRowsAfter(String docId, String anchorText, List<RowData> rows, int startRow)
            throws TableException {
        tableRowOperationService.addTableRowsAfter(docId, anchorText, rows, startRow);
    }

    @Override
    public void appendTableRowsAfter(String docId, String anchorText, List<RowData> rows)
            throws TableException {
        tableRowOperationService.appendTableRowsAfter(docId, anchorText, rows);
    }

    @Override
    public void deleteTableRows(String docId, String tableAnchor, int startRow, int endRow)
            throws TableException {
        tableRowOperationService.deleteTableRows(docId, tableAnchor, startRow, endRow);
    }

    // ============ 表格操作 - 按列 ============

    @Override
    public void addTableColumnsAfter(String docId, String anchorText, List<ColumnData> columns, int startCol)
            throws TableException {
        tableColumnOperationService.addTableColumnsAfter(docId, anchorText, columns, startCol);
    }

    @Override
    public void appendTableColumnsAfter(String docId, String anchorText, List<ColumnData> columns)
            throws TableException {
        tableColumnOperationService.appendTableColumnsAfter(docId, anchorText, columns);
    }

    @Override
    public void deleteTableColumns(String docId, String tableAnchor, int startCol, int endCol)
            throws TableException {
        tableColumnOperationService.deleteTableColumns(docId, tableAnchor, startCol, endCol);
    }
    
    // ============ 表格操作 - 单元格 ============
    
    @Override
    public void setCellContent(String docId, String tableAnchor, int row, int col, String content)
            throws CellException {
        cellOperationService.setCellContent(docId, tableAnchor, row, col, content);
    }

    @Override
    public void setCellsContent(String docId, String tableAnchor, int startRow, int startCol,
                               List<List<String>> content) throws CellException {
        cellOperationService.setCellsContent(docId, tableAnchor, startRow, startCol, content);
    }

    @Override
    public void mergeCells(String docId, String tableAnchor, int startRow, int startCol,
                          int endRow, int endCol) throws CellException {
        cellOperationService.mergeCells(docId, tableAnchor, startRow, startCol, endRow, endCol);
    }

    
    @Override
    public void replaceCellsNextToMergedCell(String docId, String tableAnchor, String cellText, List<String> values)
            throws CellException {
        cellOperationService.replaceCellsNextToMergedCell(docId, tableAnchor, cellText, values);
    }
    
    // ============ 批量更新辅助方法 ============
    
    /**
     * 执行批量更新请求
     * 
     * @param docId 文档ID
     * @param updateRequests 更新请求列表
     * @return 是否成功
     * @throws DocumentOperationException 操作失败时抛出
     */
    private boolean executeBatchUpdate(String docId, List<UpdateBlockRequest> updateRequests) 
            throws DocumentOperationException {
        if (updateRequests == null || updateRequests.isEmpty()) {
            return true;
        }
        
        try {
            // 如果请求数量超过最大限制，需要分批处理
            if (updateRequests.size() > MAX_BATCH_SIZE) {
                logger.debug("将{}个请求拆分为每批{}个", 
                           updateRequests.size(), MAX_BATCH_SIZE);
                
                for (int i = 0; i < updateRequests.size(); i += MAX_BATCH_SIZE) {
                    int end = Math.min(i + MAX_BATCH_SIZE, updateRequests.size());
                    List<UpdateBlockRequest> batch = updateRequests.subList(i, end);
                    
                    if (!executeSingleBatch(docId, batch)) {
                        return false;
                    }
                }
                return true;
            } else {
                return executeSingleBatch(docId, updateRequests);
            }
        } catch (Exception e) {
            throw new DocumentOperationException("执行批量更新失败: " + e.getMessage());
        }
    }
    
    /**
     * 执行单个批量更新请求
     * 
     * @param docId 文档ID
     * @param updateRequests 更新请求列表（不超过MAX_BATCH_SIZE）
     * @return 是否成功
     */
    private boolean executeSingleBatch(String docId, List<UpdateBlockRequest> updateRequests) {
        try {
            BatchUpdateDocumentBlockReq batchReq = BatchUpdateDocumentBlockReq.newBuilder()
                    .documentId(docId)
                    .documentRevisionId(-1)
                    .batchUpdateDocumentBlockReqBody(BatchUpdateDocumentBlockReqBody.newBuilder()
                            .requests(updateRequests.toArray(new UpdateBlockRequest[0]))
                            .build())
                    .build();

            // batchUpdateDocumentBlock现在直接返回数据体，失败时抛出FeishuApiException
            client.docx().batchUpdateDocumentBlock(batchReq);
            
            logger.debug("成功执行包含{}个请求的批量更新", updateRequests.size());
            return true;
            
        } catch (Exception e) {
            logger.error("错误 executing batch update", e);
            return false;
        }
    }
    
    @Override
    public void addProtectedDimension(String docId, String tableAnchor,
                                     List<ProtectedDimension> protectedDimensions,
                                     String userIdType) throws TableException {
        sheetProtectionService.addProtectedDimension(docId, tableAnchor, protectedDimensions, userIdType);
    }
}